// 11.3 关联容器操作
/**
 * 除了表9.2（第295页）中列出的类型，关联容器还定义了表11.3中列出的类型。这些类型表示容器关键字和值的类型。[插图]
 * 1. key_type     此容器类型的关键字类型
 * 2. mapped_type  每个关键字关联的类型，即值的类型，只适用于map
 * 3. value_type   对于set，与key_type相同；对于map，为pair<const key_type,mapped_type>
 * 与顺序容器一样（参见9.2.2节，第297页），我们使用作用域运算符来提取一个类型的成员——例如，map<string，int>：：key_type。
 */

#include <iterator>
#include <vector>
#include <list>
#include <deque>
#include <forward_list>
#include <string>
#include <array>
#include <stack>
#include <queue>
#include <algorithm>
#include <numeric>
using std::swap;
using std::vector, std::list, std::deque, std::forward_list, std::string, std::array, std::stack, std::queue;
#include "../Chapter07/Sales_data.h"
#include <iostream>
using std::begin, std::cbegin, std::end, std::cend, std::find, std::accumulate, std::equal, std::fill, std::fill_n, std::back_inserter;
using std::cin, std::cout, std::endl;
using std::copy, std::replace, std::replace_copy;
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <utility>
using namespace std;

int main()
{
    // 11.3.4 map的下标操作
    // map和unordered_map容器提供了下标运算符和一个对应的at函数（参见9.3.2节，第311页），如表11.6所示。
    // set类型不支持下标，因为set中没有与关键字相关联的“值”。
    // 与其他下标运算符不同的是，如果关键字并不在map中，会为它创建一个元素并插入到map中，关联值将进行值初始化（参见3.3.1节，第88页）。
    // 例如，如果我们编写如下代码[插图]
    map<string,size_t> word_count;
    word_count["Anna"] = 1; // 插入一个关键字为Anna的元素，关联值进行值初始化；然后将1赋予它
    // 对一个map使用下标操作，其行为与数组或vector上的下标操作很不相同：
    // 使用一个不在容器中的关键字作为下标，会添加一个具有此关键字的元素到map中。[插图]
    // 1. c[k]    返回关键字为k的元素；如果k不在c中，添加一个关键字为k的元素，对其进行值初始化
    // 2. c.at(k) 访问关键字为k的元素。若k不在c中，则抛出一个out_of_range异常
   auto anna = word_count.at("Anna");
   auto baaa = word_count.at("baaa"); // 抛出out_of_range异常

   // 使用下标操作的返回值
   // 当对一个map进行下标操作时，会获得一个mapped_type对象；但当解引用一个map迭代器时，会得到一个value_type对象（参见11.3节，第381页）。
   // 与其他下标运算符相同的是，map的下标运算符返回一个左值（参见4.1.1节，第121页）。
   // 由于返回的是一个左值，所以我们既可以读也可以写元素：[插图]
   cout << word_count["Anna"]; // 用Anna作为下标提取元素，会打印1
   ++word_count["Anna"];       // 提取元素，将其增加1
   cout << word_count["Anna"]; // 打印2

    return 0;
}